package com.xiaoyu.lanling.feature.login.fragment

import `in`.srain.cube.util.UTUtil
import android.os.Bundle
import android.text.Editable
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import cn.dreamtobe.kpswitch.util.KeyboardUtil
import com.xiaoyu.base.app.AppContext
import com.xiaoyu.base.app.GlobalUI
import com.xiaoyu.base.event.AppEventBus
import com.xiaoyu.base.event.SimpleEventHandler
import com.xiaoyu.base.utils.extensions.setOnClickDebounceListener
import com.xiaoyu.lanling.R
import com.xiaoyu.lanling.common.Constant
import com.xiaoyu.lanling.event.login.LoginCellphoneClickNextEvent
import com.xiaoyu.lanling.event.login.LoginCodeClickBackEvent
import com.xiaoyu.lanling.event.login.LoginEvent
import com.xiaoyu.lanling.event.login.LoginEvent.Companion.STATUS_DISABLE
import com.xiaoyu.lanling.event.login.LoginRegSmsEvent
import com.xiaoyu.lanling.feature.login.data.LoginData
import com.xiaoyu.lanling.router.Router
import com.xiaoyu.lanling.view.OnShowFragment
import com.xiaoyu.lanling.view.listener.BaseTextWatcher
import io.reactivex.Observable
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.Disposable
import io.reactivex.schedulers.Schedulers
import kotlinx.android.synthetic.main.fragment_login_code.*
import org.greenrobot.eventbus.Subscribe
import org.greenrobot.eventbus.ThreadMode
import java.util.concurrent.TimeUnit

class LoginCodeFragment : OnShowFragment() {

    companion object {
        fun newInstance(): LoginCodeFragment {
            return LoginCodeFragment()
        }
    }

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        return inflater.inflate(R.layout.fragment_login_code, container, false)
    }

    private val requestTag: Any = Any()
    private var mCellphone: String? = null

    private var mCountDownDisposable: Disposable? = null

    override fun onViewCreatedSafelyAfterAppFinishInit(view: View, savedInstanceState: Bundle?) {
        initBind()
        initEvent()
    }

    override fun onDestroy() {
        super.onDestroy()
        mCountDownDisposable?.dispose()
    }

    private fun initBind() {
        back.setOnClickDebounceListener {
            LoginCodeClickBackEvent().post()
        }
        edit_text.addTextChangedListener(object : BaseTextWatcher() {
            override fun afterTextChanged(s: Editable?) {
                if (s?.length == 4) {
                    mCellphone?.let {
                        LoginData.login(requestTag, it, s.toString())
                    }
                    KeyboardUtil.hideKeyboard(edit_text)
                }
            }
        })
        resend.setOnClickDebounceListener {
            sendSms()
        }
        change_cellphone.setOnClickDebounceListener {
            back.performClick()
        }
    }

    private fun initEvent() {
        AppEventBus.bindContainerAndHandler(this, object : SimpleEventHandler() {
            @Subscribe(threadMode = ThreadMode.MAIN)
            fun onEvent(event: LoginCellphoneClickNextEvent) {
                mCellphone = event.cellphone
                cellphone_desc.text = event.cellphone
                sendSms()
            }

            @Subscribe(threadMode = ThreadMode.MAIN)
            fun onEvent(event: LoginRegSmsEvent) {
                if (event.isNotFromThisRequestTag(requestTag)) {
                    return
                }
                startCountDown()
            }

            @Subscribe(threadMode = ThreadMode.MAIN)
            fun onEvent(event: LoginEvent) {
                if (event.isNotFromThisRequestTag(requestTag)) {
                    return
                }

                if (event.isFailed) {
                    resetNextButton()
                    return
                }
                dispatchLogin(event)
            }
        })
    }

    private fun dispatchLogin(event: LoginEvent) {
        val context = activity ?: return
        when {
            event.status == STATUS_DISABLE -> mCellphone?.let { Router.instance.gotoLockActivity(context, cellphone = it) }
            event.hasSetProfile -> Router.instance.gotoMainActivityForNew(context, 0)
            else -> Router.instance.gotoRegisterActivity(context, loginType = Constant.LoginType.CELLPHONE)
        }
        logForDispatchLogin(event.hasSetProfile, event.status)
    }

    private fun sendSms() {
        mCellphone?.let {
            disableNextButton()
            LoginData.loginRegSms(requestTag, it)

            logForSmsSend(it)
        }
    }

    private fun startCountDown() {
        val remainSecond = 60
        mCountDownDisposable?.dispose()
        mCountDownDisposable = Observable.interval(0, 1, TimeUnit.SECONDS)
                .map<Int> { passSecond: Long -> remainSecond - passSecond.toInt() }
                .subscribeOn(Schedulers.computation())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe({ second: Int ->
                    if (second == 0) {
                        resetNextButton()
                    } else {
                        resend.text = AppContext.getString(R.string.login_code_resend_disable, second.toString())
                    }
                }, { obj: Throwable -> obj.printStackTrace() }) {
                    resetNextButton()
                }
        GlobalUI.getInstance().showToast(getString(R.string.login_code_sms_send_success_toast))
    }

    private fun resetNextButton() {
        resend.text = AppContext.getString(R.string.login_code_resend_enable)
        resend.isEnabled = true
        mCountDownDisposable?.dispose()
    }

    private fun disableNextButton() {
        resend.text = AppContext.getString(R.string.login_code_resend_enable)
        resend.isEnabled = false
    }

    private fun logForSmsSend(mobile: String) {
        val params = Bundle()
        params.putString("mobile", mobile)
        UTUtil.getInstance().logEvent("login_auth_code_send", params)
        UTUtil.getInstance().flushLogEvent()
    }

    private fun logForDispatchLogin(registered: Boolean, status: String) {
        val params = Bundle()
        params.putBoolean("registered", registered)
        params.putString("status", status)
        UTUtil.getInstance().logEvent("login_auth_code_confirm", params)
        UTUtil.getInstance().flushLogEvent()
    }
}